# -*- coding: utf-8 -*-


from blog.models import Article, Tag, Category, Timeline

from .serializers import (UserModelSerializer, ArticleSerializer,
                          TimelineSerializer,TagSerializer,CategorySerializer,ToolLinkSerializer)

from rest_framework.permissions import IsAuthenticated

# from .permissions import IsAdminUserOrReadOnly

from rest_framework.response import Response
from rest_framework.views import APIView
import json
from blog.utils import MyHashEncryptor as MyHash,get_timestamp_rand
from django.template.defaultfilters import slugify
import re

class APIResponse(Response):
    def __init__(self, status='success', msg='ok', results=None, http_status=None,
                 headers=None, exception=False, content_type='application/json', **kwargs):
        # 将status、msg、results、kwargs格式化成data
        data = {
            'status': status,
            'msg': msg,
        }
        # results只要不为空都是数据：False、0、'' 都是数据 => 条件不能写if results
        if results is not None:
            data['results'] = results
        # 将kwargs中额外的k-v数据添加到data中
        data.update(**kwargs)
        super().__init__(data=data, status=http_status, headers=headers, exception=exception, content_type=content_type)


class PublicView(APIView):
    #自定义允许的操作方法
    custom_methods = ('query','add','delete','update')
    permission_classes = (IsAuthenticated,)

    APIResponse = APIResponse()

    @property
    def allowed_methods(self):
        return ['POST']
    def post(self, request, *args, **kwargs):
        # print(request.data)
        body_dict = request.data
        # body_dict = json.loads(json.dumps(eval(request.body.decode('utf-8'))))
        method_value = body_dict.get('method')
        if method_value is None:
            return APIResponse('error','must be a key \'method\',default method:query、add、delete、update.')
        if method_value not in self.custom_methods:
            return APIResponse('error',f'this api doesn\'t allow a custom method \'{method_value}\'')
        if hasattr(self,method_value):
            return getattr(self,method_value)(request,args,kwargs)
        else:
            return APIResponse('error',f'no instance of \'{method_value}\' method')

    @property
    def get_header(self):
        return self.request.successful_authenticator.get_header(self.request)
    @property
    def get_raw_token(self):
        return self.request.successful_authenticator.get_raw_token(self.get_header)
    @property
    def get_validated_token(self):
        return self.request.successful_authenticator.get_validated_token(self.get_raw_token)
    @property
    def get_user(self):
        return self.request.successful_authenticator.get_user(self.get_validated_token)
class ArticleListview(PublicView):
    """
        @desc:文章列表接口,查询文章列表
        @desc:允许操作-query
    """
    custom_methods = ('query')
    #自定义“查询”方法
    @staticmethod
    def query(request,*args,**kwargs):
        body = request.data
        pk = body.get('pk')
        if isinstance(pk,int):
            article_query = Article.objects.filter(pk=pk).first()
            many = False
        elif pk == '':
            article_query = Article.objects.all()
            many = True
        elif isinstance(pk,list) and len(pk) > 0:
            article_query = Article.objects.filter(pk__in=pk).all()
            many = True
        else:
            return APIResponse('failed', 'query need correct pk,please check pk.')
        article_serial = ArticleSerializer(article_query,many=many)
        return APIResponse(results=article_serial.data)


class ArticleDetailView(PublicView):
    """
    @desc:文章详情接口，对文章进行增删改查操作
    @desc:允许操作-add,update,query
    """
    custom_methods = ('add','update','query')
    mark_info = None

    @property
    def get_slug(self):
        num_sixteen = get_timestamp_rand() + "Article"
        slug_hash = MyHash.myencryped('md5', num_sixteen)
        return slugify("-".join(re.findall(r'[0-9a-f]{8}', slug_hash)))

    #定义添加成功响应数据
    def get_success_info(self,results):
        return {
            "info": "data adds successfully.",
            self.mark_info: results.get(self.mark_info)
        }
    def add(self,request, *args, **kwargs):
        """
        单增：接口：article/   数据：{...}
        群增：接口：article/   数据：[{...}, ..., {...}]
        逻辑：将数据给系列化类处理，数据的类型关系到 many 属性是否为True
        """
        add_data = request.data.get('data')


        if isinstance(add_data, dict):
            many = False
            add_data['author_id'] = self.get_user.pk
            add_data['slug'] = self.get_slug
        elif isinstance(add_data, list):
            many = True
            for data_inx in range(len(add_data)):
                add_data[data_inx].update({"author_id": self.get_user.pk})
                add_data[data_inx].update({"slug": self.get_slug})
        else:
            return APIResponse('failed','data error.')

        article_ser = ArticleSerializer(data=add_data, many=many)
        article_ser.is_valid(raise_exception=True)
        try:
            article_obj = article_ser.save()
            tmp_results = ArticleSerializer(article_obj, many=many).data
            self.mark_info = 'title'
            if many:
                results = list(map(lambda x: self.get_success_info(x), tmp_results))
            else:
                results = self.get_success_info(tmp_results)
        except AssertionError as e:
            results = { "errmsg":"AssertionError," + e.__str__()}
        except KeyError as e:
            results = { "errmsg":"KeyError," + e.__str__()}
        except Exception:
            results = { "errmsg":"data added unsuccessfully."}
        return APIResponse(results=results)


